package com.hlf.modules.api.service.impl;

import com.hlf.common.constants.Constants;
import com.hlf.common.exception.BusinessException;
import com.hlf.common.utils.*;
import com.hlf.modules.api.entity.BusinessKind;
import com.hlf.modules.api.entity.CheckCodeCount;
import com.hlf.modules.api.entity.Checkcode;
import com.hlf.modules.api.mapper.BusinessKindMapper;
import com.hlf.modules.api.mapper.CheckCodeCountMapper;
import com.hlf.modules.api.service.CheckcodeService;
import com.hlf.modules.api.service.SMSService;
import com.hlf.modules.sys.service.SysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.MessageFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;

/**
 * 短信服务层接口实现类
 *
 */
@Service
public class SMSServiceImpl implements SMSService {

    private static final Logger logger = LoggerFactory.getLogger(SMSServiceImpl.class);

    @Autowired
    CheckcodeService checkcodeService;
    @Autowired
    SysUserService sysUserService;
    @Autowired
    private BusinessKindMapper businessKindMapper;
    @Autowired
    private CheckCodeCountMapper checkCodeCountMapper;
    @Autowired
    PropertieUtil propertieUtil;

    /**
     * 短信计数
     * @param mobile
     * @param messageType
     */
    public void sendCount(String mobile ,Byte messageType){
        //计数
        CheckCodeCount checkCodeCount = checkCodeCountMapper.selectByPhoneAndBizType(mobile,messageType);
        if (checkCodeCount == null){
            checkCodeCount = new CheckCodeCount();
            checkCodeCount.setId(IdWorkerFactory.nextId());
            checkCodeCount.setMobilePhone(mobile);
            checkCodeCount.setCountType((byte) 1);
            checkCodeCount.setBizType(messageType);
            checkCodeCount.setCount(1);
            Date date = new Date();
            checkCodeCount.setDate(date);
            checkCodeCount.setInsertDate(date);
            checkCodeCount.setLastUpdateDate(date);
            checkCodeCountMapper.insert(checkCodeCount);
        }else {
            LocalDate day = LocalDate.now();
            Date date = checkCodeCount.getDate();
            Instant instant = date.toInstant();
            ZoneId zoneId = ZoneId.systemDefault();
            // atZone()方法返回在指定时区从此Instant生成的ZonedDateTime。
            LocalDate localDate = instant.atZone(zoneId).toLocalDate();
            boolean equals = day.equals(localDate);
            //当天
            if (equals){
                Integer count = checkCodeCount.getCount();
                if (count > Integer.valueOf(propertieUtil.getPropertie("ADAY_UPDATE_PWD_NUM"))){
                    throw new BusinessException("您在一天之内获取验证码已经超过允许次数!");
                }
                checkCodeCount.setCount(checkCodeCount.getCount()+1);
                checkCodeCountMapper.updateByPrimaryKeySelective(checkCodeCount);
            }else {
                //非当天
                checkCodeCount.setCount(1);
                checkCodeCount.setDate(new Date());
                checkCodeCountMapper.updateByPrimaryKeySelective(checkCodeCount);
            }
        }
    }

    @Override
    public void sendMoblieVCode(String mobile, Integer codType, int userType) {
        boolean isMobile = ValidateUtils.isMobileNO(mobile);
        boolean mobileExist = sysUserService.mobileCount(mobile) > 0;
        if(isMobile){
            if(Constants.MESSAGE_TYPE_REGISTER == codType){//只针对注册
                if(!mobileExist){
                    this.getMoblieVCode(mobile,codType);
                }else{
                    throw new BusinessException("手机号码已被注册!");
                }
            }else {
                //如果不是注册,计数
                if(!mobileExist){
                    throw new BusinessException("该手机号码未注册!");
                }
                sendCount(mobile ,codType.byteValue());
                this.getMoblieVCode(mobile,codType);
            }
        }else{
            throw new BusinessException("手机号码校验失败!");
        }
    }

    @Override
    public void getMoblieVCode(String mobile,Integer codeType) {
        if("ALDY".equals(SmsConstants.SMS_GALLERY)){
            sendMsgByALDY(mobile,codeType);
        }else if("UMS".equals(SmsConstants.SMS_GALLERY)){
            sendMsgByUMS(mobile, codeType);
        }else{
            sendMsgByCSMD(mobile,codeType);
        }
    }

    /**
     * 校验验证码是否正确
     */
    @Override
    public boolean checkAuthCode(String mobile,String code,int codeType){
        Checkcode checkcode = checkcodeService.findNearestCode(mobile, code, codeType);
        if (checkcode != null) {
            // 验证码有效时间,单位毫秒
            int validTime = Integer.valueOf(propertieUtil
                    .getPropertie("FORGET_PWD_VALID_TIME")) * 60 * 1000;
            Date now = new Date();
            long time = now.getTime() - checkcode.getCodSendTime().getTime();
            if (time > validTime) {
                logger.error("校验短信验证码,验证码已失效。");
                throw new BusinessException("验证码已失效");
            } else if (Constants.COD_USED_YES==checkcode.getCodUsed()) {
                logger.error("校验短信验证码,验证码已被使用。");
                throw new BusinessException("验证码已被使用");
            } else {
                // 改变验证码状态为已使用
                checkcodeService.changeCodeUsed(checkcode.getCodId());
            }
        } else {
            logger.error("校验短信验证码,验证码不正确。");
            throw new BusinessException("验证码不正确");
        }
        return true;
    }


    //创世漫道短信通道
    private void sendMsgByCSMD(String mobile,Integer codType){
        logger.info("发送短信类型{}",codType);
        String code;
        // 开发模式验证码使用默认验证码
        if(Constants.MODE_TYPE_DEV.equals(Constants.MODE_TYPE)){
            code = SmsConstants.DEFAULT_VERIFICATION_CODE_6;
            logger.debug("开发环境请使用默认验证码{}验证",code);
        }else{
            code = (int) ((Math.random() * 9 + 1) * 100000) + "";
        }
        String content="";
        int validTime = Integer.valueOf(propertieUtil.getPropertie("FORGET_PWD_VALID_TIME"));
        if(SmsConstants.CODE_MERCHANT_REGISTER==codType){
            content=propertieUtil.getPropertie("MERCHANT_REGISTER_CONTENT");
        }else if(SmsConstants.CODE_PERSONAL_REGISTER==codType){
            content=propertieUtil.getPropertie("PERSONAL_REGISTER_CONTENT");
        }else if(SmsConstants.CODE_MERCHANT_BONUS_ENCHASHMENT==codType){
            content=propertieUtil.getPropertie("BONUS_ENCHASHMENT_CONTENT");
        }else if(SmsConstants.CODE_MERCHANT_BIND_TONGGUANG==codType){
            content=propertieUtil.getPropertie("BIND_TONGGUANG_CONTENT");
        }else if(SmsConstants.CODE_STOREMANAGER_BIND_POS==codType){
            content=propertieUtil.getPropertie("BIND_POS_CONTENT");
        }else{
            throw new BusinessException("发送短信类型异常");
        }
        content = MessageFormat.format(content, code, validTime);
        boolean sendResult = true;
        // 非开发模式才发送短信验证码
        if(!Constants.MODE_TYPE_DEV.equals(Constants.MODE_TYPE)){
            sendResult = SMSUtil.getInstance().sendSMSToMobile(mobile, content);
        }
        if(sendResult){
            Checkcode checkcode=new Checkcode();
            checkcode.setCodType(codType);
            checkcode.setCodMobile(mobile);
            checkcode.setCodCode(code);
            checkcode.setCodUsed(Constants.COD_USED_NO);
            checkcode.setCodSendTime(new Date());
            checkcodeService.insert(checkcode);
        }
    }

    //阿里大于短信通道
    private void sendMsgByALDY(String mobile,Integer codType){
        logger.info("阿里大于短信通道，发送短信类型{}",codType);
        String code;
        // 开发模式验证码使用默认验证码
        if(Constants.MODE_TYPE_DEV.equals(Constants.MODE_TYPE)){
            code = SmsConstants.DEFAULT_VERIFICATION_CODE_6;
            logger.debug("开发环境请使用默认验证码{}验证",code);
        }else{
            code = (int) ((Math.random() * 9 + 1) * 100000) + "";
        }

        int validTime = Integer.valueOf(propertieUtil.getPropertie("FORGET_PWD_VALID_TIME"));
        String templateCode = "";
        if(SmsConstants.CODE_MERCHANT_REGISTER==codType){
            templateCode = SmsConstants.ALDY_SMS_TEMPLATE_REGISTER;
        }else if(SmsConstants.CODE_PERSONAL_REGISTER==codType){
            templateCode = SmsConstants.ALDY_SMS_TEMPLATE_BIND;
        }else if(SmsConstants.CODE_MERCHANT_BONUS_ENCHASHMENT==codType){
            templateCode = SmsConstants.ALDY_SMS_TEMPLATE_BONUS;
        }else if(SmsConstants.CODE_MERCHANT_FILL_INFO==codType){
            templateCode = SmsConstants.ALDY_SMS_TEMPLATE_FILL;
        }else if(SmsConstants.CODE_MERCHANT_BIND_TONGGUANG==codType){
            templateCode = SmsConstants.ALDY_SMS_TEMPLATE_BIND_TONGGUANG;
        }else if(SmsConstants.CODE_STOREMANAGER_BIND_POS==codType){
            templateCode = SmsConstants.ALDY_SMS_TEMPLATE_BIND_POS;
        }else{
            throw new BusinessException("发送短信类型异常");
        }
        logger.info("阿里大于短信通道，发送短信模板{}",templateCode);
        boolean sendResult = true;
        String paramJosn = "{\"code\":\""+code+"\",\"time\":\""+validTime+"\"}";
        // 非开发模式才发送短信验证码
        if(!Constants.MODE_TYPE_DEV.equals(Constants.MODE_TYPE)){
            //阿里大于短信通道，一分钟之内对同一手机号码发短信会有异常
            int res = checkcodeService.getDifftimeByNow(mobile);
            logger.info("阿里大于发送短信模板(时间差：秒){}",res);
            if(res>=60){
                boolean timesLimit = checkcodeService.getCodIdByNowAndLimitCount(mobile, 4, 1);
                if(!timesLimit){
                    boolean timesLimit2 = checkcodeService.getCodIdByNowAndLimitCount(mobile, 9, 24);
                    if(!timesLimit2){
                        sendResult = SMSUtil.getInstance().sendMsgALDY(templateCode, mobile, paramJosn);
                    }else{
                        logger.error("阿里大于发送短信模板,超过一天允许数。{}",mobile);
                        throw new BusinessException("您在一天之内获取验证码已经超过允许次数。");
                    }
                }else{
                    logger.error("阿里大于发送短信模板,超过一小时允许数。{}",mobile);
                    throw new BusinessException("您在一小时之内获取验证码已经超过允许次数。");
                }
            }else{
                logger.error("阿里大于发送短信模板,一分钟之内多次获取。{}",mobile);
                throw new BusinessException("请勿频繁操作，"+(60-res)+"秒后再获取验证码。");
            }
        }
        if(sendResult){
            Checkcode checkcode=new Checkcode();
            checkcode.setCodType(codType);
            checkcode.setCodMobile(mobile);
            checkcode.setCodCode("123456");
            checkcode.setCodUsed(Constants.COD_USED_NO);
            checkcode.setCodSendTime(new Date());
            checkcodeService.insert(checkcode);
        }

    }

    //一信通短信通道
    private void sendMsgByUMS(String mobile,Integer codType){
        logger.info("一信通短信通道,发送短信类型{}",codType);
        String code;
        // 开发模式验证码使用默认验证码
        if(Constants.MODE_TYPE_DEV.equals(Constants.MODE_TYPE)){
            code = SmsConstants.DEFAULT_VERIFICATION_CODE_6;
            logger.debug("开发环境请使用默认验证码{}验证",code);
        }else{
            code = (int) ((Math.random() * 9 + 1) * 100000) + "";
        }
        String content=propertieUtil.getPropertie("TONGGUANG_SMS_CONTENT");
        content = MessageFormat.format(content, code,"通莞金服",",");
        boolean sendResult = true;
        // 非开发模式才发送短信验证码
        if(!Constants.MODE_TYPE_DEV.equals(Constants.MODE_TYPE)){
            int res = checkcodeService.getDifftimeByNow(mobile);
            logger.info("一信通短信通道(时间差：秒){}",res);
            if(res>=60){
                boolean timesLimit = checkcodeService.getCodIdByNowAndLimitCount(mobile, 4, 1);
                if(!timesLimit){
                    boolean timesLimit2 = checkcodeService.getCodIdByNowAndLimitCount(mobile, 9, 24);
                    if(!timesLimit2){
                        sendResult = SMSUtil.getInstance().sendMsgUMS(mobile, content);
                    }else{
                        logger.error("一信通短信通道,超过一天允许数。{}",mobile);
                        throw new BusinessException("您在一天之内获取验证码已经超过允许次数。");
                    }
                }else{
                    logger.error("一信通短信通道,超过一小时允许数。{}",mobile);
                    throw new BusinessException("您在一小时之内获取验证码已经超过允许次数。");
                }
            }else{
                throw new BusinessException("请勿频繁操作，"+(60-res)+"秒后再获取验证码。");
            }
        }

        if(sendResult){
            Checkcode checkcode=new Checkcode();
            checkcode.setCodType(codType);
            checkcode.setCodMobile(mobile);
            checkcode.setCodCode(code);
            checkcode.setCodUsed(Constants.COD_USED_NO);
            checkcode.setCodSendTime(new Date());
            checkcodeService.insert(checkcode);
        }
    }

    /**
     * 主营类目
     * @return
     */
    @Override
    public List<BusinessKind> getKind() {
        return businessKindMapper.selectAll();
    }
}
